package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class AutoFillAspect {


//    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
//     加上代表谁缩小范围 不加也行
    /*
    切入点
     */
    @Pointcut("@annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointcut(){}
    /**
     * 前置通知，在通知中进行公共字段的赋值
     */
   @Before("autoFillPointcut()")//对加了这个@AutoFill注解方法进行增强
   public void autoFill(JoinPoint joinPoint){//joinPoint 被增强的原始方法
        //获取被增强方法的方法签名
       MethodSignature signature = (MethodSignature)joinPoint.getSignature();
       // 通过增强方法签名 获取方法对象
       Method method = signature.getMethod();
       // method指的是被增强方法对象  比如insert update这些方法对象
       // 获取注解
       AutoFill autoFill = method.getAnnotation(AutoFill.class);
       OperationType operationType = autoFill.value();

       log.info("开始进行公共字段自动填充");
       //自动填充目标要确定  原始方法的参数 实体对象  可能是 Employee Category Dish SetMeal
       //拿到参数 对象 进行 功能的增强
       Object[] args = joinPoint.getArgs();
       if(args==null || args.length==0){
           //说明 参数没有或者有问题
           return;//没有必要增强 因为没有目标了！！！！
       }

       Object entry = args[0];// entry 就是要增强的对象
      // 准备赋值的数据
       LocalDateTime now = LocalDateTime.now();
       Long currentId = BaseContext.getCurrentId();
       // 我得知道  增强的是添加还是更新
    if(operationType==OperationType.INSERT){//标明是新增
        log.info("这里判断出来是新增");
        // 做四个字段增强 --- 自动填充 四个字段 属性值
        //  已知实体对象 entry 里面有个属性叫 createTime  且有set方法
        try {

//            Method setCreateTime = entry.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
            Method setCreateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setUpdateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setCreateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER,Long.class);
            Method setUpdateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            //反射形式执行方法
            setCreateTime.invoke(entry,now);//  entry.setCreateTime(now)
            setUpdateTime.invoke(entry,now);
            setCreateUser.invoke(entry,currentId);
            setUpdateUser.invoke(entry,currentId);

        } catch (Exception e) {
            e.printStackTrace();
            log.info("没有对应set方法");
        }

    }else{//更新
        log.info("这里判断出来是更新");
        // 做两个字段的增强--- 自动填充 两个个字段 属性值
        try {

            Method setUpdateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            //反射形式执行方法
            setUpdateTime.invoke(entry,now);
            setUpdateUser.invoke(entry,currentId);

        } catch (Exception e) {
            e.printStackTrace();
            log.info("没有对应set方法");
        }
    }
   }
}
